package com.example.lt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.lt.constant.MessageConstants;
import com.example.lt.constant.RedisConstant;
import com.example.lt.entity.Captcha;
import com.example.lt.entity.dto.FindPWDTO;
import com.example.lt.entity.dto.LoginDTO;
import com.example.lt.entity.dto.RegisterDTO;
import com.example.lt.entity.user.User;
import com.example.lt.exception.BaseException;
import com.example.lt.exception.MyLoginException;
import com.example.lt.exception.RegisterException;
import com.example.lt.service.CaptchaService;
import com.example.lt.service.LoginService;
import com.example.lt.service.user.UserService;
import com.example.lt.util.EmailUtil;
import com.example.lt.util.RedisUtil;
import lombok.RequiredArgsConstructor;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
 * @Author 小涛Tao
 * @Date: 2024/07/27/17:00
 * version 1.0 注释：
 **/
@Service
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {

    private final UserService userService;

    private final CaptchaService captchaService;

    private final RedisUtil redisUtil;

    private final EmailUtil emailUtil;

    /**
     * 注册用户
     * @param registerDTO
     * @return
     */
    @Override
    public Boolean register(RegisterDTO registerDTO) {
        final String email = registerDTO.getEmail();
        // 检查该邮箱是否已被注册
        if (userService.getUserByEmail(email)) throw new RegisterException(MessageConstants.EMAIL_EXIST);

        final String code = registerDTO.getCode(); // 获取用户输入的邮箱验证码

        checkCode(email, code); // 检查邮箱验证码

        return userService.register(registerDTO);
    }

    /**
     * 用户登录
     * @param loginDTO
     * @return
     */
    @Override
    public User login(LoginDTO loginDTO) {
        final String password = loginDTO.getPassword();
        // 根据邮箱账号查询用户信息
        User user = userService.getOne(new LambdaQueryWrapper<User>()
                .eq(User::getEmail, loginDTO.getEmail()));
        if (ObjectUtils.isEmpty(user)) {
            throw new MyLoginException(MessageConstants.ACCOUNT_NOT_EXIST);
        }

        if (!password.equals(user.getPassword())) {
            throw new MyLoginException(MessageConstants.PASSWORD_ERROR);
        }
        return user;
    }

    /**
     * 找回密码
     * @param findPWDTO
     * @return
     */
    @Override
    public Boolean findPassword(FindPWDTO findPWDTO) {
        // 检查该邮箱是否有注册
        if (!userService.getUserByEmail(findPWDTO.getEmail())) throw new BaseException(MessageConstants.EMAIL_NOT_EXIST);

        checkCode(findPWDTO.getEmail(), String.valueOf(findPWDTO.getCode())); // 验证邮箱验证码

        return userService.findPassword(findPWDTO);
    }

    /**
     * 获取注册时需要的图形验证码
     * @param response
     * @param uuid
     */
    @Override
    public void Captcha(HttpServletResponse response, String uuid) throws IOException {
        if (ObjectUtils.isEmpty(uuid)) {
            throw new RegisterException(MessageConstants.UUID_EMPTY);
        }
        // 指示浏览器不要缓存响应
        response.setHeader("Cache-Control", "no-store, no-cache");
        response.setContentType("image/jpeg");

        // 获取验证码图片
        BufferedImage image = captchaService.getCaptcha(uuid);
        ServletOutputStream outputStream = response.getOutputStream();
        ImageIO.write(image, "jpg", outputStream);
        // 关闭输入流
        IOUtils.closeQuietly(outputStream);
    }

    /**
     * 用户获取邮箱验证码
     * @param captcha
     * @return
     */
    @Override
    public Boolean getCode(Captcha captcha) {
        String email = captcha.getEmail();
        // 1、验证用户输入的图形验证码
        if (!captchaService.validate(captcha)) {
            return false;
        }
        // 2、获取六位数的随机邮箱验证码
        String code = CaptchaServiceImpl.getSixCode();
        // 3、把验证码存入redis中，时间为 5 分钟
        redisUtil.set(RedisConstant.EMAIL_CODE + email, code, RedisConstant.EMAIL_CODE_TIME);
        // 4、向目标 email 发送验证码code，这邮箱发送任务是交给线程池来执行的
        // TODO 注意：为了测试方便，这里的邮箱发送注释了
        // emailUtil.sendRegisterCode(email, code);
        return true;
    }

    /**
     * 检查邮箱验证码
     * @param email
     * @param code
     * @return
     */
    @Override
    public Boolean checkCode(String email, String code) {
        if (ObjectUtils.isEmpty(email) || ObjectUtils.isEmpty(code)) {
            throw new RegisterException(MessageConstants.ARG_ISNULL);
        }

        final Object o = redisUtil.get(RedisConstant.EMAIL_CODE + email); // 获取系统生成的邮箱验证码

        if (o == null) throw new RegisterException(MessageConstants.EMAIL_CODE_EXPIRE); // 验证邮箱验证码是否过期
        if (!o.equals(code)) throw new RegisterException(MessageConstants.EMAIL_CODE_ERROR); // 验证邮箱验证码是否正确

        return true;
    }
}
